package com.um.springcloud.dubbo.cluster;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.cluster.interceptor.ClusterInterceptor;
import org.apache.dubbo.rpc.cluster.specifyaddress.Address;
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;

import java.util.Arrays;

/**
 * 调用拦截器
 *
 * @author 甘天伟
 * @since 2024/1/24
 * 版权所有 广州优匠科技有限公司
 */
@Slf4j
@Activate(group = CommonConstants.CONSUMER)
public class DeviceClusterInterceptor implements ClusterInterceptor {

    DeviceClusterProperties properties;

    DeviceClusterUtil util;

    public DeviceClusterInterceptor() {
        properties = SpringUtil.getBean(DeviceClusterProperties.class);
        util = SpringUtil.getBean(DeviceClusterUtil.class);

        log.info("DeviceClusterInterceptor loaded");
    }

    @Override
    public void before(AbstractClusterInvoker<?> clusterInvoker, Invocation invocation) {
        if (!properties.isInterceptor() || invocation == null) {
            return;
        }

        DeviceKey deviceKey = (DeviceKey) Arrays.stream(invocation.getArguments())
                .filter(arg -> arg instanceof DeviceKey)
                .findFirst()
                .orElse(null);
        if (deviceKey == null) {
            return;
        }

        String endpoint = util.getDeviceEndpoint(deviceKey.getKey());
        if (StrUtil.isBlank(endpoint)) {
            return;
        }

        String host = endpoint;
        int port = 0;
        if (endpoint.contains(":")) {
            String[] arr = endpoint.split(":");
            host = arr[0];
            port = Integer.parseInt(arr[1]);
        }

        log.debug("put endpoint {} to method {} for device {}", endpoint, invocation.getMethodName(), deviceKey.getKey());
        invocation.put(Address.name, new Address(host, port, true));
    }

    @Override
    public void after(AbstractClusterInvoker<?> clusterInvoker, Invocation invocation) {

    }
}
